package com.gss.stockLedger.service;

import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import org.apache.log4j.Logger;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.gss.stockLedger.dao.QueryStockDAO;
import com.gss.stockLedger.dao.QueryStockNoDaoSupportDAO;
import com.gss.stockLedger.domain.FIFOReportDTO;
import com.gss.stockLedger.form.ReportGenerateForm;
import com.gss.stockLedger.util.ApplicationConstants;

@Service
public class FifoReportGenerationThreadedService {
	
	Logger logger = Logger.getLogger(getClass());
	@Autowired
	QueryStockDAO queryStockDAO;
	
	@Autowired
	QueryStockNoDaoSupportDAO queryStockNoDaoSupportDAO;
	
	/*@Autowired
	ExcelCreationService excelCreationService;*/
	
	public static Set<String> Consumption_Transaction_Type = new HashSet<String>();
	public static Set<String> Receipt_Transaction_Type = new HashSet<String>();
	SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
	SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("ddMMyyyyHHmmss");	
	public int sheetCounter=0;
	
	static {
		Consumption_Transaction_Type.add("CONS");
		Consumption_Transaction_Type.add("FOC");
		Consumption_Transaction_Type.add("RTV");
		Consumption_Transaction_Type.add("SCRAP");
		Consumption_Transaction_Type.add("CAPTIVE");
		Consumption_Transaction_Type.add("SALES");
		
		Receipt_Transaction_Type.add("ZGRIR");
		Receipt_Transaction_Type.add("CUSTOM");
		Receipt_Transaction_Type.add("COSTPRICE");
		Receipt_Transaction_Type.add("RETRO");
		Receipt_Transaction_Type.add("FOREX");
		Receipt_Transaction_Type.add("INVADJ");
		Receipt_Transaction_Type.add("OPENING");
		
	}
	
	public boolean generateFIFOReport(ReportGenerateForm reportForm, Date date) {
			logger.debug("entered FIFO");
			boolean resultOfSucess = false;
			GenerateExcelThread generateExcelThread = null;
			
			FifoDataProcessorThread multiThread = null;
			long startTime = System.currentTimeMillis();

			
		try{
			
			Date previousTransactDate = null;
			List<FIFOReportDTO> finalReportList ;
			
			List<Object[]> partIdList =queryStockNoDaoSupportDAO.getUniquePartIds(reportForm.getInvType(), reportForm.getLastPartId(), reportForm.getCompanyName());
			logger.debug("partIdList: " + partIdList.size());
			
			LinkedList<FIFOReportDTO> transactionQ = null;
			Stack<FIFOReportDTO> consumedStack = null;
			LinkedList<FIFOReportDTO> transactionQForReport = null;
			boolean generateNegativePartAnalysis = reportForm.isNegativePartVariable();
			List<FIFOReportDTO> negativePartList = new ArrayList<FIFOReportDTO>();
			Workbook workbook;
			if(!reportForm.isNegativePartVariable()){
				String sheetName = reportForm.getReportCategory() + reportForm.getReportType();														//added by ashish
				
				workbook = ExcelCreationService.createExcelFile(sheetName,reportForm.getValuationMethod(),reportForm.getStartDate(),
						reportForm.getEndDate(),date, reportForm.getReportCategory(),reportForm.getReportType(), reportForm.getInvType(), reportForm.getCompanyName());			//added by ashish
				logger.debug("Default Excel WorkBook Created");
				
				// create excel generation thread
				generateExcelThread = new GenerateExcelThread(workbook, reportForm,date);
				generateExcelThread.setRunning(true);
				
				generateExcelThread.start();
			}
			
			Calendar lastTransactionDate = Calendar.getInstance();
			Calendar currentTransactionDate = Calendar.getInstance();
			long prevClosingQuantity = 0;
			int partIdCounter = 0;
			int totalPartIds = partIdList.size();
			
			ThreadCounter threadCounter = new ThreadCounter();
			threadCounter.setNumberOfThreads(0);
			
			for (Object[] object : partIdList) {
				
				//implementing multiple threads
				while(threadCounter.getNumberOfThreads() >= 25){
					Thread.sleep(1000l);
				}
				
				multiThread = new FifoDataProcessorThread(generateExcelThread,object,generateNegativePartAnalysis,negativePartList,queryStockNoDaoSupportDAO,
						reportForm,threadCounter);
				Thread thread = new Thread(multiThread);
				thread.start();
				threadCounter.setNumberOfThreads(1);
				System.out.println("Processing: " + ++partIdCounter + " of " + totalPartIds + " ++++Part Id: " + object[0].toString() + " +++Inv. Type: " + object[1].toString());
				
			}
			while(threadCounter.getNumberOfThreads() >0){
				System.out.println("Waiting for threads to finish: " + threadCounter.getNumberOfThreads());
				Thread.sleep(1000l);
			}
			resultOfSucess = true;
			if(!generateNegativePartAnalysis){
				while(generateExcelThread.getPartId_data_map().size() > 0){
					Thread.sleep(2000l);
					System.out.println("Entries left: " + generateExcelThread.getPartId_data_map().size());
				}
				generateExcelThread.setRunning(false);
				generateExcelThread.join();
				System.out.println("%%%%%%%%%%%%%%%%%%%%%%%%  STILL WRITING  %%%%%%%%%%%%%%%%%%%%%%%%%%");
			}else{
				// write data of generated list to an excel
				Integer excelRowCounter = 9;
				workbook = ExcelCreationService.generateNegativePartExcel(ApplicationConstants.negativePartSheetName, reportForm.getStartDate(), reportForm.getEndDate(), reportForm.getCompanyName());
				Integer finalRowCounter = ExcelCreationService.appendNegativePartExcelSheet(workbook, excelRowCounter, negativePartList,reportForm);
				
				System.out.println("Final Row Counter" + finalRowCounter);
				
				String pathName = ApplicationConstants.pathToExcel + System.getProperty("file.separator")
						+ ApplicationConstants.negativePartSheetName + System.getProperty("file.separator")
						+ simpleDateFormat.format(date) + System.getProperty("file.separator");
				String fileName = simpleDateFormat.format(reportForm.getStartDate()) 
						+ simpleDateFormat.format(reportForm.getEndDate()) + simpleDateFormat2.format(date) + ".xls";
				
				File createDir = new File(pathName);
				createDir.mkdirs();
				
				FileOutputStream fileOut = new FileOutputStream(pathName + fileName);
				workbook.write(fileOut);
				fileOut.flush();
				fileOut.close();
				resultOfSucess = true;
				return resultOfSucess;
			}

		}
		catch (Throwable e) {
			e.printStackTrace();
		}
		finally{
			if(null != generateExcelThread){
				generateExcelThread.setRunning(false);
			}
			System.out.println("time taken: " + (System.currentTimeMillis() - startTime));
		}
		logger.debug("resultOfSucess: "+resultOfSucess);
		return resultOfSucess;
	}		
}
